#pragma once

#include "znx_conn.h"
#include "znx_listener.h"
#include "znx_event_loop.h"
#include "comm/znx_array.h"


//////////////////// tcp accepter ///////////////////

typedef struct {
    int                                 nthreads;
    znx_event_loop_data_t               *datas;
    znx_thread_base_t                   *threads;
} znx_tcp_accepter_t;


typedef struct {
    znx_conn_t                          conn;
    znx_listener_t                      *l;
} znx_tcp_listener_item_t;


typedef struct {
    znx_array_t                         *ls;
    znx_event_t                         event;
    int64_t                             version;
} znx_tcp_loop_data_t;


// run in main thread.
void znx_tcp_accepter_start(int nthreads);

// run in main thread.
void znx_tcp_accepter_stop();

void znx_tcp_accepter_notify();

extern char *znx_tcp_accept_thread_tag;

static inline znx_bool_t
current_thread_is_tcp_accepter_thread()
{
    if (current_thread_base == NULL) {
        return ZNX_FALSE;
    }

    if (current_thread_base->tag != znx_tcp_accept_thread_tag) {
        return ZNX_FALSE;
    }

    return ZNX_TRUE;
}



//////////////// tcp connect ////////////////////

typedef struct {
    unsigned                nodelay:1;
    unsigned                quickack:1;
} znx_tcp_connect_opt_t;


typedef void (*znx_tcp_connect_handler_pt)(void *data,
    znx_conn_t *conn, znx_result_t res);


void znx_tcp_connect_setup(znx_conn_t *conn,
    znx_address_t *address, znx_address_t *bind_address,
    znx_tcp_connect_opt_t *opts, int64_t timeout_ms,
    znx_tcp_connect_handler_pt connect_handler, void *user_data);


void znx_tcp_connect_cancel(znx_conn_t *conn);
